package response

import (
	"errors"
	"gitee.com/yms-zero/go-library/ivalidator"
	"gitee.com/yms-zero/go-library/until"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go-api/internal/err"
	"go-api/internal/tool"
	"net/http"
)

const (
	// DefaultSuccessCode 成功
	DefaultSuccessCode int    = 0
	DefaultSuccessMsg  string = "Success"

	// DefaultErrCode 服务内部错误
	DefaultErrCode int    = 500
	DefaultErrMsg  string = "Internal error"

	// DefaultNotFoundCode 未知的路由
	DefaultNotFoundCode int    = 404
	DefaultNotFoundMsg  string = "Unknown route"

	// DefaultParamsCode 参数错误
	DefaultParamsCode int    = 400
	DefaultParamsMsg  string = "Parameter error"
)

type ApiHandlerFunc func(c *gin.Context) (r interface{}, e error)

func ApiHandleConvert(handler ApiHandlerFunc) gin.HandlerFunc {

	return func(c *gin.Context) {

		r, e := handler(c)

		status, ar := ApiResponse(r, e)
		c.JSON(status, ar)
	}
}

func ApiResponse(r interface{}, e error) (status int, ar ApiResult) {
	var (
		code int
		msg  string
	)

	if e != nil {
		var (
			businessErr   err.BusinessErr
			validationErr validator.ValidationErrors
		)
		if errors.As(e, &validationErr) {
			status = http.StatusBadRequest
			code = DefaultParamsCode
			msg = ivalidator.Translate(validationErr, tool.Trans())

		} else if errors.As(e, &businessErr) {

			status = http.StatusOK
			code = businessErr.Code()
			msg = businessErr.Msg()

		} else {
			status = http.StatusInternalServerError
			code = DefaultErrCode
			msg = e.Error()
		}

	} else {
		status = http.StatusOK
		code = DefaultSuccessCode
		msg = DefaultSuccessMsg
	}
	return status, NewApiResult(code, msg, r)
}

type ApiResult struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

func NewApiResult(code int, msg string, data interface{}) ApiResult {
	if until.IsNil(data) {
		data = struct{}{}
	}

	return ApiResult{
		Code: code,
		Msg:  msg,
		Data: data,
	}
}
